package com.example.springbootjwt.filter;

import com.example.springbootjwt.model.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/7/11 18:35
 */
public class JwtLoginFilter extends AbstractAuthenticationProcessingFilter
{
    private static final Log log= LogFactory.getLog(JwtLoginFilter.class);

    //这里要重写一个构造，参数是defaultFilterProcessesUrl，authenticationManager
    public JwtLoginFilter(String defaultFilterProcessesUrl, AuthenticationManager authenticationManager)
    {
        super(new AntPathRequestMatcher(defaultFilterProcessesUrl));
        setAuthenticationManager(authenticationManager);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse resp) throws AuthenticationException, IOException, ServletException
    {
        //认证方式以json形式进行验证
        User user = new ObjectMapper().readValue(req.getInputStream(),User.class);
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
        return getAuthenticationManager().authenticate(token);
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException
    {
        log.info("authResult:"+authResult.toString());
        /**
         * authResult:org.springframework.security.authentication.UsernamePasswordAuthenticationToken@3b57d2cd:
         * Principal: org.springframework.security.core.userdetails.User@586034f:
         * Username: admin; Password: [PROTECTED];
         * Enabled: true; AccountNonExpired: true;
         * credentialsNonExpired: true;
         * AccountNonLocked: true;
         * Granted Authorities: ROLE_admin;
         * Credentials: [PROTECTED];
         * Authenticated: true;
         * Details: null;
         * Granted Authorities: ROLE_admin
         */
        Collection<? extends GrantedAuthority> authorities = authResult.getAuthorities();
        StringBuffer buffer = new StringBuffer();
        for (GrantedAuthority authority : authorities)
        {
            buffer.append(authority.getAuthority()).append(",");
        }

        //authorities:ROLE_admin,
        log.info("authorities:"+buffer);
        String jwt = Jwts.builder()
                .claim("authorities", buffer)
                //getName这个方法，在Authentication的继承类里面Principal
                .setSubject(authResult.getName())
                //设置过期时间
                .setExpiration(new Date(System.currentTimeMillis() + 60 * 60 * 1000))
                //设置签名使用的签名算法和签名使用的秘钥
                .signWith(SignatureAlgorithm.HS512, "leo123456")
                .compact();
        Map<String, String> map = new HashMap<>();
        map.put("token",jwt);
        map.put("msg","登陆成功");
        response.setContentType("application/json;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.write(new ObjectMapper().writeValueAsString(map)); //将对象转为json字符串
        writer.flush();
        writer.close();
    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException
    {
        Map<String, String> map = new HashMap<>();
        map.put("msg","登陆失败");
        response.setContentType("application/json;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.write(new ObjectMapper().writeValueAsString(map));
        writer.flush();
        writer.close();
    }
}
